package is.ru.honn.rupin.service;

import is.ru.honn.rupin.data.BoardDataGateway;
import is.ru.honn.rupin.data.PinDataGateway;
import is.ru.honn.rupin.data.UserDataGateway;
import is.ru.honn.rupin.domain.Board;
import is.ru.honn.rupin.domain.Gender;
import is.ru.honn.rupin.domain.Pin;
import is.ru.honn.rupin.domain.User;
import is.ruframework.data.RuDataAccessFactory;
import is.ruframework.domain.RuException;
import org.springframework.dao.EmptyResultDataAccessException;

import java.util.List;
import java.util.logging.Logger;

/**
 * @author Einar Sigurðsson
 * @version 1.0, 21 Oct 2012
 *
 * An implementation of PinService using Java Database Connections
 */
public class PinServiceData implements PinService{

    //The logger for this class
    Logger log = Logger.getLogger(this.getClass().getName());

    //The gateways being used for Data
    private UserDataGateway userDataGateway;
    private PinDataGateway pinDataGateway;
    private BoardDataGateway boardDataGateway;

    /**
     * The empty constructor sets up the gateways with
     * beans userData, pinData and boardData from data.xml
     * using RuDataAccessFactory
     */
    public PinServiceData() {
        RuDataAccessFactory factory = null;
        try{
            factory = RuDataAccessFactory.getInstance("data.xml");
        } catch (RuException e) {
            log.severe("Unable to load data specification in data.xml" + e.getMessage());
        }
        userDataGateway = (UserDataGateway)factory.getDataAccess("userData");
        pinDataGateway = (PinDataGateway)factory.getDataAccess("pinData");
        boardDataGateway = (BoardDataGateway)factory.getDataAccess("boardData");
    }

    /**
     * creates a new user and passes it to the database
     * @param username the desired username
     * @param firstName first name of the user
     * @param lastName Last name of the user
     * @param email    email of the user
     * @param password password of the user
     * @param gender   gender of the user (Gender enum)
     * @return the newly created user object
     * @throws UsernameExistsException if the username already exists
     */
    @Override
    public User signUpUser(String username, String firstName, String lastName, String email,
                           String password, Gender gender)
            throws UsernameExistsException {
        if(getUser(username)== null){
            User newUser = new User(username, firstName, lastName, email, password, gender);
            userDataGateway.add(newUser);
            return newUser;
        }
        else{
            throw new UsernameExistsException("This username already exists");
        }
    }

    /**
     * gets the user with the specified username from the database
     * @param username username of the user
     * @return User object of the user with the username
     */
    @Override
    public User getUser(String username) {
        User returnUser;
        try{
         returnUser = userDataGateway.getUserByUsername(username);
        }catch(EmptyResultDataAccessException e){
            return null;
        }
        return returnUser;
    }

    /**
     * gets the board with the given boardname created by the user
     * @param username username of the user
     * @param boardname name of the board
     * @return The board with name boardname and creator username
     * @return null if no board was found
     */
    @Override
    public Board getBoard(String username, String boardname) {
        return boardDataGateway.getBoard(boardname, username);
    }

    /**
     * Gets all boards created by the user from the database
     * @param username username of the user
     * @return all boards made by the user
     */
    @Override
    public List<Board> getBoards(String username) {

        return boardDataGateway.getBoardsByUsername(username);
    }

    /**
     * adds a board to the ru_boards table with the given properties
     * @param username creator of the board
     * @param boardname name of the board
     * @param category category of the board
     * @return the newly created board
     * @throws UserNotFoundException if the user doesn't exist
     */
    @Override
    public Board createBoard(String username, String boardname, String category) throws UserNotFoundException {
        User creator = getUser(username);
        if(creator == null)
            throw new UserNotFoundException("The user doesn't exist");
        Board newBoard = new Board(boardname, category);
        newBoard.setCreator(creator);
        boardDataGateway.add(newBoard);
        return newBoard;
    }

    /**
     * Adds a pin to a board in the database
     * @param username creator of the pin
     * @param boardname name of the board
     * @param link        link of the pin
     * @param description description of the pin
     * @param image       image of the pin
     * @return the newly created pin
     * @throws BoardNotFoundException if the board wasn't found
     */
    @Override
    public Pin createPin(String username, String boardname, String link, String description, String image) throws BoardNotFoundException {
        Board b = getBoard(username, boardname);
        if(b == null)
            throw new BoardNotFoundException("The board doesn't exist");
        Pin newPin = new Pin(link, description, image);
        newPin.setBoard(b);
        newPin.setCreator(getUser(username));
        pinDataGateway.add(newPin);
        return newPin;
    }


    /**
     * gets all pins on the specified board
     * @param username creator of the board
     * @param boardname name of the board
     * @return all pins on the specified board as a list
     */
    @Override
    public List<Pin> getPinsOnBoard(String username, String boardname) {
        return pinDataGateway.getPinsByBoardnameAndCreator(boardname, username);

    }
}
